package com.yundingai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yundingai.domain.dto.RecommendUserDTO;
import com.yundingai.domain.entity.AllUser;
import com.yundingai.domain.entity.UserSocialData;
import com.yundingai.mapper.UserFriendMapper;
import com.yundingai.mapper.AllUserMapper;
import com.yundingai.mapper.UserSocialDataMapper;
import com.yundingai.service.RecommendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
/**
 * @Author HuangZhengmin
 * @desc 好友推荐服务实现类
 * @Date 2025/7/22 14:54
 * @Version 1.0
 */
@Service
@Slf4j
public class RecommendServiceImpl implements RecommendService {

  @Autowired
  private UserFriendMapper userFriendMapper;
  @Autowired
  private AllUserMapper allUserMapper;
  @Autowired
  private UserSocialDataMapper userSocialDataMapper;

  @Override
  public List<RecommendUserDTO> getRecommendations(Integer userId, int limit) {
    // 打印开始获取推荐列表的日志
    log.info("开始获取推荐列表，userId={}, limit={}", userId, limit);
    try {
      // 获取候选用户ID集合
      Set<Integer> candidateIds = getCandidateUserIds(userId);
      // 打印候选用户ID集合的日志
      log.debug("候选用户ID集合: {}", candidateIds);

      // 过滤掉已经建立连接的用户
      filterExistingConnections(userId, candidateIds);
      // 打印过滤后的候选用户日志
      log.debug("过滤后的候选用户: {}", candidateIds);

      // 根据相关性对候选用户进行排序
      List<Integer> sortedIds = sortCandidatesByRelevance(userId, new ArrayList<>(candidateIds));
      // 取出前limit个用户ID
      List<Integer> finalIds = sortedIds.size() > limit ? sortedIds.subList(0, limit) : sortedIds;

      // 构建推荐结果
      List<RecommendUserDTO> result = buildRecommendationResult(userId, finalIds);
      // 打印成功生成推荐列表的日志
      log.info("成功生成推荐列表，数量={}", result.size());
      return result;
    } catch (Exception e) {
      // 打印获取推荐列表失败的日志
      log.error("获取推荐列表失败: ", e); // 打印完整堆栈
      // 抛出运行时异常，保留原始异常
      throw new RuntimeException("获取推荐失败", e); // 保留原始异常
    }
  }


  private Set<Integer> getCandidateUserIds(Integer userId) {
    // 获取候选用户ID集合
    Set<Integer> candidateIds = new HashSet<>();

    // 基于共同好友的推荐
    candidateIds.addAll(findByMutualFriends(userId));

    // 获取用户社交数据
    UserSocialData userData = userSocialDataMapper.selectByUserId(userId);
    if (userData != null) {
      // 基于通讯录的推荐
      if (StringUtils.hasText(userData.getContactsHashed())) {
        candidateIds.addAll(findByContacts(userData.getContactsHashed()));
      }

      // 基于教育/工作经历的推荐
      candidateIds.addAll(findByEducationOrWork(userData));
    }

    return candidateIds;
  }


  private List<Integer> findByMutualFriends(Integer userId) {
    // 1. 获取用户的好友列表
    List<Integer> userFriends = userFriendMapper.findFriendIdsByUserId(userId);
    if (CollectionUtils.isEmpty(userFriends)) {
      return Collections.emptyList();
    }

    // 2. 获取好友的好友(二度人脉)
    return userFriends.stream()
            .flatMap(friendId -> userFriendMapper.findFriendIdsByUserId(friendId).stream())
            .filter(id -> !id.equals(userId)) // 排除自己
            .collect(Collectors.toList());
  }

// 根据联系人哈希值查找用户ID
  private List<Integer> findByContacts(String contactsHashed) {
    // 调用userSocialDataMapper的findUserIdsByContactsHashed方法，传入联系人哈希值，返回用户ID列表
    return userSocialDataMapper.findUserIdsByContactsHashed(contactsHashed);
  }

  private List<Integer> findByEducationOrWork(UserSocialData userData) {
    // 创建一个QueryWrapper对象，用于构建查询条件
    QueryWrapper<UserSocialData> queryWrapper = new QueryWrapper<>();
    // 如果用户的教育信息不为空，则添加查询条件
    if (StringUtils.hasText(userData.getEducationInfo())) {
      queryWrapper.eq("education_info", userData.getEducationInfo());
    }
    // 如果用户的职业信息不为空，则添加查询条件
    if (StringUtils.hasText(userData.getWorkInfo())) {
      queryWrapper.or().eq("work_info", userData.getWorkInfo());
    }
    //添加查询条件 兴趣信息
    if (StringUtils.hasText(userData.getInterestInfo())) {
      queryWrapper.or().eq("interest_info", userData.getInterestInfo());
    }
    //添加查询条件 地址信息
    if (StringUtils.hasText(userData.getLocationInfo())) {
      queryWrapper.or().eq("location_info", userData.getLocationInfo());
    }
    // 查询用户ID
    queryWrapper.select("user_id");

    // 返回查询结果
    return userSocialDataMapper.selectList(queryWrapper).stream()
            .map(UserSocialData::getUserId)
            .collect(Collectors.toList());
  }

  private void filterExistingConnections(Integer userId, Set<Integer> candidateIds) {
    // 获取已存在的好友关系
    List<Integer> existingConnections = new ArrayList<>();
    for (Integer candidateId : candidateIds) {
      if (userFriendMapper.existsConnection(userId, candidateId)) {
        existingConnections.add(candidateId);
      }
    }
    candidateIds.removeAll(existingConnections);
    candidateIds.remove(userId); // 排除自己
  }

  private List<Integer> sortCandidatesByRelevance(Integer userId, List<Integer> candidateIds) {
    // 简化为随机排序，实际项目中可以根据多种因素计算权重
    Collections.shuffle(candidateIds);
    return candidateIds;
  }

  private List<RecommendUserDTO> buildRecommendationResult(Integer userId, List<Integer> userIds) {
    // 判断用户ID列表是否为空
    if (CollectionUtils.isEmpty(userIds)) {
      // 如果为空，返回空列表
      return Collections.emptyList();
    }

    // 批量查询用户信息
    List<AllUser> users = allUserMapper.selectBatchIds(userIds);
    // 批量查询社交数据（优化查询性能）
    List<Integer> userIdList = users.stream().map(AllUser::getUserId).collect(Collectors.toList());
    Map<Integer, UserSocialData> socialDataMap = userIdList.stream()
            .map(id -> {
              QueryWrapper<UserSocialData> wrapper = new QueryWrapper<>();
              wrapper.eq("user_id", id);
              return userSocialDataMapper.selectOne(wrapper);
            })
            .filter(Objects::nonNull)
            .collect(Collectors.toMap(UserSocialData::getUserId, data -> data));
    // 获取当前用户数据
    UserSocialData currentUserData = userSocialDataMapper.selectByUserId(userId);

    // 获取当前用户好友列表
    List<Integer> userFriends = userFriendMapper.findFriendIdsByUserId(userId);

    // 返回推荐结果列表
    return users.stream().map(user -> {
      RecommendUserDTO dto = new RecommendUserDTO();
      // 设置基础信息
      dto.setUserId(user.getUserId());
      dto.setUsername(user.getUsername());
      dto.setNickname(user.getNickname());
      dto.setAvatarUrl(user.getAvatarUrl());
      dto.setGender(user.getGender());

      // 获取候选用户社交数据
      UserSocialData candidateData = socialDataMap.get(user.getUserId());

      // 构建推荐理由
      List<String> reasons = new ArrayList<>();

      /* 1. 基于社交关系的推荐 */
      if (!CollectionUtils.isEmpty(userFriends)) {
        // 共同好友计算
        List<Integer> candidateFriends = userFriendMapper.findFriendIdsByUserId(user.getUserId());
        if (!CollectionUtils.isEmpty(candidateFriends)) {
          Set<Integer> friendSet = new HashSet<>(userFriends);
          Set<Integer> mutualFriends = candidateFriends.stream()
                  .filter(friendSet::contains)
                  .collect(Collectors.toSet());

          if (!mutualFriends.isEmpty()) {
            dto.setMutualFriends(mutualFriends.size());
            reasons.add(mutualFriends.size() + "个共同好友");
          }
        }

        // 修正二度人脉判断
        if (candidateFriends != null && !Collections.disjoint(userFriends, candidateFriends)) {
          reasons.add("有共同好友圈");
        }
      }

      /* 2. 基于社交数据的推荐 */
      if (currentUserData != null && candidateData != null) {
        // 同城推荐（使用locationInfo字段）
        if (StringUtils.hasText(currentUserData.getLocationInfo()) &&
                currentUserData.getLocationInfo().equals(candidateData.getLocationInfo())) {
          reasons.add("同城：" + currentUserData.getLocationInfo());
        }

        // 校友推荐
        if (StringUtils.hasText(currentUserData.getEducationInfo()) &&
                currentUserData.getEducationInfo().equals(candidateData.getEducationInfo())) {
          reasons.add("校友：" + currentUserData.getEducationInfo());
        }

        // 同事推荐
        if (StringUtils.hasText(currentUserData.getWorkInfo()) &&
                currentUserData.getWorkInfo().equals(candidateData.getWorkInfo())) {
          reasons.add("同职业：" + currentUserData.getWorkInfo());
        }

        // 相同爱好兴趣推荐
        if (StringUtils.hasText(currentUserData.getInterestInfo()) &&
                currentUserData.getInterestInfo().equals(candidateData.getInterestInfo())) {
          reasons.add("同爱好：" + currentUserData.getInterestInfo());
        }

        // 通讯录联系人
        if (StringUtils.hasText(currentUserData.getContactsHashed()) &&
                currentUserData.getContactsHashed().equals(candidateData.getContactsHashed())) {
          reasons.add("通讯录联系人");
        }
      }

      /* 3. 默认推荐理由 */
      if (reasons.isEmpty()) {
        reasons.add("你可能认识的人");
      }

      dto.setReasons(reasons);
      return dto;
    }).collect(Collectors.toList());
  }
}
